package io.mft.runtime.config.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.mft.commons.config.ConfigProvider;
import io.mft.commons.exception.MFTException;
import io.mft.dev.base.cache.RegionConfig;
import io.mft.dev.base.cache.RegionGenericConfig;
import io.mft.dev.base.cache.RegionHashConfig;
import io.mft.dev.base.cache.RegionConfig.Storage;
import io.mft.runtime.config.ConfigLoader;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ApplicationConfigCacheRegionLoader implements ConfigLoader<List<RegionConfig<?>>>{

	@Override
	public List<RegionConfig<?>> load(String appId) {
		List<RegionConfig<?>> regionConfigs=new ArrayList<>();
		Map<String, RegionConfig<?>> regionConfigMap=new HashMap<>();
		Map<String, ClassLoader> classLoaderMap=new HashMap<String, ClassLoader>();
		
		List<ClassLoader> classLoaders=ConfigProvider.getConfigClassLoaders();
		classLoaders.forEach(classLoader->{
			try {
				Map<String, Object> cacheRegion=ConfigProvider.getConfigObject(classLoader,"cacheRegion");
				if (cacheRegion!=null) {
					cacheRegion.keySet().forEach(datasourceKey->{
						List<Map<String, Object>> regionConfigMaps=ConfigProvider.getMapValue(cacheRegion,datasourceKey);
						regionConfigMaps.forEach(map->{
							try {
								JSONObject jsonObject=JSONUtil.parseObj(map);
								String storage=String.valueOf(map.get("storage"));
								RegionConfig<?> regionConfig=null;
								if (Storage.hash.name().equals(storage)) {
									regionConfig=jsonObject.toBean(RegionHashConfig.class, false);
								}else if (Storage.generic.name().equals(storage)) {
									regionConfig=jsonObject.toBean(RegionGenericConfig.class, false);
								}
								if (regionConfig==null) {
									throw new MFTException("不支持缓存配置["+storage+"]项storage，请检查！");
								}	
								regionConfig.setDatasourceId(datasourceKey);
								regionConfig.setOwnerPluginId("cache");
								regionConfig.init();
								String key=datasourceKey+"."+regionConfig.getAliasKey();
								if (regionConfigMap.containsKey(key)) {
									StringBuilder msg=new StringBuilder();
									msg.append("当前缓存RegionConfig数据源["+datasourceKey+"]缓存KEY["+regionConfig.getAliasKey()+"]归属应用目录["+classLoader.getResource(".").getPath()+"]");
									msg.append("存在于应用目录["+classLoaderMap.get(key).getResource(".").getPath()+"]数据源["+datasourceKey+"]");
									throw new MFTException(msg.toString());									
								}
								regionConfigMap.put(datasourceKey, regionConfig);
								classLoaderMap.put(key, classLoader);
							} catch (MFTException e) {
								log.error("",e);
							}catch (Exception e) {
								log.error("应用插件["+classLoader.getResource(".").getPath()+"]数据源["+datasourceKey+"]缓存块["+JSONUtil.toJsonStr(map)+"]RegionConfig配置解析异常",e);
							}
						});
					});					
				}
			} catch (Exception e) {
				log.error("应用插件["+classLoader.getResource(".").getPath()+"]缓存块配置解析异常",e);
			}
		});
		regionConfigs.addAll(regionConfigMap.values());
		return regionConfigs;
	}
	
	
}
